OpenSSH
OpenSSH is the standard open-source implementation of the SSH protocol used for secure remote login, file transfers, and remote command execution over untrusted networks. It provides the sshd server (to accept connections) and client tools such as ssh, scp, and sftp. For VPS and WordPress server operations, OpenSSH is the primary remote administration channel and must be configured carefully to reduce brute-force risk and prevent lockouts.
Background and history
SSH was created to replace insecure remote access tools (such as Telnet and rsh) by providing encryption, authentication, and integrity protection. OpenSSH emerged as a widely adopted open-source implementation and became the default SSH stack on most Linux distributions. Over time, OpenSSH added stronger cryptography defaults, better key types (such as Ed25519), and more configuration controls for modern hardening baselines.
Adoption and where it’s commonly used
OpenSSH is used across:
- Linux servers (Ubuntu/Debian, RHEL-based, Alpine)
- Cloud/VPS fleets for remote administration
- CI/CD and automation (key-based access, forced commands)
- Secure file transfer workflows (SFTP)
Maintained by
- Maintained by the OpenSSH project community.
Best when to use
- You need secure remote shell access to servers.
- You need secure file transfer (SFTP) without opening additional services.
- You need controlled remote administration with keys, restricted users, and auditing.
- You want a widely supported protocol and tooling for automation.
Not suitable when
- You need browser-based or zero-trust access without inbound ports exposed (use a bastion/overlay access model).
- You cannot safely expose SSH to the internet and lack firewalling or access control.
- You need centralized enterprise access governance that mandates different tooling.
Compatibility notes
-
Linux distributions typically ship OpenSSH by default, but versions differ.
-
Service name differs by distro:
- Debian/Ubuntu:
ssh - RHEL/Fedora/Rocky/AlmaLinux:
sshd
- Debian/Ubuntu:
-
Configuration file locations:
- Server:
/etc/ssh/sshd_configand often/etc/ssh/sshd_config.d/*.conf - Client:
/etc/ssh/ssh_configand~/.ssh/config
- Server:
-
Logs differ by distro:
- Debian/Ubuntu:
/var/log/auth.log - RHEL-based:
/var/log/secure
- Debian/Ubuntu:
-
Some environments use upstream firewalls (cloud security groups) in addition to host firewalls.
Changes to sshd configuration can lock you out immediately after a reload/restart. Keep an existing SSH session open, validate config with sshd -t, test in a second session, and ensure firewall rules allow your access path before applying changes.
Concepts and how it works
OpenSSH uses a client-server model:
- The server daemon
sshdlistens on a TCP port (default22) and enforces authentication and access policies. - The client
sshnegotiates encryption, authenticates (preferably using keys), then opens a session or executes a command.
Installation
Debian/Ubuntu
sudo apt update
sudo apt install openssh-server openssh-client
RHEL/CentOS Stream/Rocky/AlmaLinux/Fedora
sudo dnf install openssh-server openssh-clients
Alpine
sudo apk add openssh
Enable and start the server (if not already enabled):
sudo systemctl enable --now ssh 2>/dev/null || sudo systemctl enable --now sshd
Core components
| Component | Purpose |
|---|---|
| -- | |
sshd | SSH server daemon |
ssh | SSH client |
sftp | Secure file transfer client |
scp | Secure copy (legacy; use SFTP where feasible) |
ssh-keygen | Generate and manage keys |
ssh-agent / ssh-add | Key caching for client sessions |
authorized_keys | Server-side list of permitted public keys |
Common commands (daily operations)
Connect to a server
ssh user@server_ip
Custom port:
ssh -p 2581 user@server_ip
Use a specific key:
ssh -i ~/.ssh/id_ed25519 user@server_ip
Copy a file (prefer SFTP in modern workflows)
SFTP interactive session:
sftp -P 2581 user@server_ip
Non-interactive upload example:
sftp -P 2581 user@server_ip <<'EOF'
put ./local-file /tmp/local-file
EOF
Run a remote command
ssh -p 2581 user@server_ip "uname -a && uptime"
Key-based authentication
Key-based authentication is the standard for secure SSH.
Generate an Ed25519 key (recommended)
ssh-keygen -t ed25519 -a 64 -f ~/.ssh/id_ed25519
Install the public key on the server
ssh-copy-id -p 2581 user@server_ip
Or manually append to the server:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
cat >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
Server configuration basics (sshd_config)
Validate config before applying
sudo sshd -t
Inspect effective runtime configuration
sudo sshd -T | head
Common hardening settings
Prefer drop-in files in /etc/ssh/sshd_config.d/ when available.
Example drop-in: /etc/ssh/sshd_config.d/10-hardening.conf
# Prefer key auth
PasswordAuthentication no
KbdInteractiveAuthentication no
# Disable direct root login
PermitRootLogin no
# Limit who can log in
AllowUsers admin ops
# Reduce noise (optional)
MaxAuthTries 3
LoginGraceTime 30
Apply safely:
sudo sshd -t
sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd
Disabling password authentication requires that at least one working public key is installed and tested for your admin user. Confirm access in a second session before closing the original session.
Port management
Check what port SSH is listening on
sudo ss -tulpen | grep sshd
Change SSH port safely (summary)
- Allow new port in firewall and provider security group.
- Set
Port <new_port>(drop-in preferred). - Validate:
sudo sshd -t - Reload SSH.
- Confirm listener:
sudo ss -tulpen | grep <new_port> - Test new login in a second session.
- Optionally close port 22 after confirmation.
SSH forwarding and tunnels
Local port forward (common for admin access to internal services)
Example: expose remote MySQL locally (only when access controls are appropriate):
ssh -L 3307:127.0.0.1:3306 -p 2581 user@server_ip
Then connect locally to 127.0.0.1:3307.
Port forwarding can bypass network segmentation and firewall intent. Use it only for controlled admin workflows, bind to localhost, and close tunnels when done.
Logging and auditing
View SSH authentication logs
Debian/Ubuntu:
sudo tail -n 200 /var/log/auth.log
RHEL-based:
sudo tail -n 200 /var/log/secure
Systemd journal (portable):
sudo journalctl -u ssh -n 200 --no-pager 2>/dev/null || sudo journalctl -u sshd -n 200 --no-pager
Troubleshooting
Cannot connect (timeout)
Likely causes:
- Firewall/security group blocks the port
- Wrong IP (IPv4 vs IPv6)
sshdnot listening or service down
Checks on the server (console access if SSH is unavailable):
sudo ss -tulpen | grep sshd || true
sudo systemctl status ssh 2>/dev/null || sudo systemctl status sshd
Connection refused
Likely causes:
sshdnot listening on that port- Service not running
- Connecting to the wrong port
Check effective ports:
sudo sshd -T | grep -i '^port '
Authentication failure
Likely causes:
- Wrong username
- Key not installed or wrong key used
- Permissions on
~/.sshincorrect AllowUsers/AllowGroupsrestrictions
Server-side checks:
id <user>
sudo ls -ld /home/<user> /home/<user>/.ssh 2>/dev/null || true
sudo ls -l /home/<user>/.ssh/authorized_keys 2>/dev/null || true
sudo sshd -T | grep -E '^(allowusers|allowgroups|passwordauthentication|permitrootlogin)'
sshd reload fails
Validate and inspect logs:
sudo sshd -t
sudo journalctl -u ssh -n 200 --no-pager 2>/dev/null || sudo journalctl -u sshd -n 200 --no-pager
Security notes
- Prefer Ed25519 keys and protect private keys with passphrases.
- Disable password authentication where feasible.
- Disable direct root SSH login; use a sudo-capable admin user.
- Restrict SSH access by IP (firewall allowlist) when possible.
- Use rate limiting / banning (for example Fail2Ban) to reduce brute-force impact.
- Keep OpenSSH updated as part of regular patching.
Quick reference
| Goal | Command |
|---|---|
| -- | - |
| Install (Ubuntu/Debian) | sudo apt install openssh-server openssh-client |
| Service status | systemctl status ssh || systemctl status sshd |
| Validate config | sudo sshd -t |
| Show effective config | sudo sshd -T |
| Check listening ports | sudo ss -tulpen | grep sshd |
| Connect | ssh user@host |
| Connect custom port | ssh -p 2581 user@host |
| Copy key | ssh-copy-id -p 2581 user@host |
| View logs | journalctl -u ssh -n 200 --no-pager || journalctl -u sshd -n 200 --no-pager |